package org.codingq92.basic.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * java锁的种类</br></br>
 * 悲观锁：认为自己在使用数据的时候一定有其他的线程来修改数据导致并发问题，所以每次操作必须先将使用的数据加锁，确保只有自己在修改，别的线程无法修改。</br>
 * 适应场景：写比较多的场景</br>
 * 代表：Synchronized</br>
 * <p>
 * 乐观锁：认为自己使用的数据不会被其他线程修改，所以每次操作的时候不需要加锁，只是在修改数据的时候去判断之前有没有线程已经将数据变更。其实就是CAS算法。</br>
 * 适应场景：读比较多的场景（不适合写操作频繁的场景，因为在写操作频繁时，数据冲突的概率增大，可能导致多次重试，降低性能。）</br>
 * 代表：java的原子类</br>
 * <p>
 * 自旋锁(借鉴CAS思想)：当一个线程尝试获取一个被其他线程占用的锁时，它不会立即进入阻塞状态，而是在原地循环尝试获取锁，直到获取到锁或者达到一定的自旋次数（如果设置了自旋次数限制）。</br>
 * （如果锁被占用的时间较长，自旋会浪费 CPU 资源，因为线程一直在循环等待，没有做其他有用的工作。）</br>
 * <p>
 * 互斥锁：是一种最基本的锁类型，同一时刻只允许一个线程访问共享资源，其他线程想要访问该资源必须等待，直到持有锁的线程释放锁。</br>
 * 适应场景：</br>
 * 代表：Synchronized</br>
 * <p>
 * 可重入锁：指的是同一个线程在外层方法获取锁之后，内层方法仍然能获取该锁，即允许一个线程对同一把锁进行多次加锁。在释放锁时，需要释放与加锁次数相同的次数，锁才会真正释放。<br/>
 * 适应场景：</br>
 * 代表：ReentrantLock</br>
 *
 * @author: CodingQ92
 * @date: 2025/6/3 22:19
 */
public class LockDemo {

    public static void main(String[] args) throws InterruptedException {
        ExecutorService pool = Executors.newFixedThreadPool(10);
        CAS_Runnable task = new CAS_Runnable();
        for (int i = 0; i < 5; i++) {
            pool.execute(task);
        }
        pool.shutdown();
        Thread.sleep(5000);
        System.out.println(count.get());
    }

    private static final AtomicInteger count = new AtomicInteger(100);

    static class CAS_Runnable implements Runnable {
        @Override
        public void run() {
            int oldVal;
            int newVal;
            do {
                oldVal = count.get();
                newVal = oldVal - 1;
            } while (!count.compareAndSet(oldVal, newVal));
        }
    }

}
